package com.bianmin.Controller;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.bianmin.Mapper.ArticleMapper;
import com.bianmin.Mapper.OrderMapper;
import com.bianmin.Model.Article;
import com.bianmin.Model.Goods;
import com.bianmin.Model.Order;
import com.bianmin.coomen.Util;
import com.bianmin.coomen.payUtil.WechatPayValidator;
import com.bianmin.coomen.payUtil.WxPayConfig;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;


@RestController
@RequestMapping("api/wxPayCallBack")
public class WxPayCallBackController {

    @Resource
    private WxPayConfig wechatPayConfig;

    @Resource
    private Verifier verifier;

    private final ReentrantLock lock = new ReentrantLock();

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private ArticleMapper articleMapper;


    /**
     * 支付回调处理
     *
     * @param request
     * @param response
     * @return
     */
    @PostMapping("payNotify")
    public ResponseEntity<String>  payNotify(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("支付回调");

        // 处理通知参数
        Map<String, Object> bodyMap = getNotifyBody(request);
        if (bodyMap == null) {
            return falseMsg();
        }

        if (lock.tryLock()) {
            try {
                // 解密resource中的通知数据
                String resource = bodyMap.get("resource").toString();
                Map<String, Object> resourceMap = WechatPayValidator.decryptFromResource(resource, wechatPayConfig.getApiV3Key(), 1);
                System.out.println(resourceMap);
                String orderNo = resourceMap.get("out_trade_no").toString();

                //更新订单状态
                Order order = orderMapper.selectOrderByprepayId(orderNo);
                order.setStatus(1);
                orderMapper.updateById(order);

                //获取到商品信息
                Goods goods = orderMapper.selectGoodsWithOrderNo(orderNo);

                // 获取到文章详情
                Article article = orderMapper.selectArticleByOrderId(orderNo);

                //根据订单信息。调整文章的时间
                if (article.getTopEndTime() == null || article.getTopEndTime() < Util.currentTimesStamp()) {
                    article.setTopEndTime((int) (Util.currentTimesStamp() + goods.getSecond()));
                }else{
                    article.setTopEndTime(article.getTopEndTime() + goods.getSecond());
                }

                //更新数据
                articleMapper.updateById(article);
            } finally {
                //要主动释放锁
                lock.unlock();
            }
        }

        //成功应答
        return trueMsg();
    }


    private Map<String, Object> getNotifyBody(HttpServletRequest request) {
        //处理通知参数
        String body = WechatPayValidator.readData(request);
//        log.info("退款回调参数：{}", body);

        // 转换为Map
        Map<String, Object> bodyMap = JSONObject.parseObject(body, new TypeReference<Map<String, Object>>() {
        });
        // 微信的通知ID（通知的唯一ID）
        String notifyId = bodyMap.get("id").toString();
        // 验证签名信息
        WechatPayValidator wechatPayValidator
                = new WechatPayValidator(verifier, notifyId, body);
        if (!wechatPayValidator.validate(request)) {
            System.out.println("通知验签失败");
            return null;
        }
        System.out.println("通知验签成功");
        return bodyMap;
    }

    private ResponseEntity<String> falseMsg() {
        // 失败应答
        String responseXml = "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.TEXT_XML);
        return new ResponseEntity<>(responseXml, headers, HttpStatus.OK);
    }

    private ResponseEntity<String> trueMsg() {
        // 成功应答
        String responseXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.TEXT_XML);
        return new ResponseEntity<>(responseXml, headers, HttpStatus.OK);
    }

}
